package com.example.worklab.floating

import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
import android.view.ViewConfiguration
import android.view.animation.DecelerateInterpolator
import android.widget.FrameLayout
import com.example.worklab.R
import com.google.android.material.imageview.ShapeableImageView
import kotlin.math.abs
import kotlin.math.roundToInt

class FloatView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr), OnTouchListener {

    private var mViewWidth = 0
    private var mViewHeight = 0
    private var mToolBarHeight = dp2px(56F)
    private var mDragDistance = 0.5

    private var mDownX: Float = 0f
    private var mDownY: Float = 0f
    private var slop: Int

    init {
        slop = ViewConfiguration.get(context).scaledPagingTouchSlop
        initView()
    }

    private fun initView() {
        layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply {
            topMargin = mToolBarHeight
        }

        val imageView = ShapeableImageView(context).apply {
            setImageResource(R.mipmap.ic_launcher)
        }
        addView(imageView)
        setOnTouchListener(this)
        post {
            mViewWidth = this.width
            mViewHeight = this.height
        }
    }

    private var mFirstX: Int = 0
    private var mFirstY: Int = 0

    override fun onTouch(v: View?, event: MotionEvent): Boolean {
        val x = event.x
        val y = event.y
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                mDownX = event.x
                mDownY = event.y

                mFirstX = event.rawX.roundToInt()
                mFirstY = event.rawY.roundToInt()
            }

            MotionEvent.ACTION_MOVE -> {
                offsetLeftAndRight((x - mDownX).toInt())
                offsetTopAndBottom((y - mDownY).toInt())
            }

            MotionEvent.ACTION_UP -> {}
            else -> {}
        }
        return true
    }

    /**
     * 上下吸边
     */
    private fun adsorbTopAndBottom(event: MotionEvent) {
        if (isOriginFromTop()) {
            //上半屏
            val centerY = mViewHeight / 2 + abs(event.rawY - mFirstY)
            if (centerY < getAdsorbHeight()) {
                //滑动距离 < 半屏=吸顶
                val topY = 0f + mToolBarHeight
                animate().setInterpolator(DecelerateInterpolator()).setDuration(300)
                    .y(topY)
                    .start()
            } else {
                val bottomY = getContentHeight() - mViewHeight
                animate().setInterpolator(DecelerateInterpolator()).setDuration(300)
                    .y(bottomY.toFloat())
                    .start()
            }
        }
    }

    private fun isOriginFromTop(): Boolean {
        return mFirstY < getScreenHeight() / 2
    }

    private fun isOriginLeft(): Boolean {
        return mFirstX < getScreenWidth() / 2
    }

    private fun getAdsorbHeight(): Double {
        return getScreenHeight() * mDragDistance
    }

    private fun getAdsorbWidth(): Double {
        return getScreenWidth() * mDragDistance
    }

    private fun getScreenHeight(): Int {
        return resources.displayMetrics.heightPixels
    }

    private fun getScreenWidth(): Int {
        return resources.displayMetrics.widthPixels
    }

    private fun getContentHeight(): Int {
        var height = 0
        (context as? Activity)?.window?.decorView?.findViewById<FrameLayout>(android.R.id.content)
            ?.let {
                height = it.bottom
            }
        return height
    }

    private fun dp2px(dp: Float): Int {
        val density = resources.displayMetrics.density
        return (dp * density).toInt()
    }
}